package de.bht.fb6.cg1.exercise1;

import java.awt.Color;
import java.util.Arrays;

/**
 * Implements a basic {@link ColorModelInterface} filled with some basic functionality.
 * 
 * The object usualy represents a color in a specefic color space.
 * 
 * @author Dominik Eckelmann
 */
abstract public class AbstractColorModel implements ColorModelInterface {

    /**
     * represents the current color in the colorspace.
     */
    protected int[] modelColor;

    /**
     * stores the current color as {@link Color} object.
     */
    protected Color color;

    /**
     * creates a new Object to a specefic color.
     * 
     * @param c     color the object represents.
     */
    public AbstractColorModel(final Color c) {
        modelColor = new int[getComponentCount()];
        setColor(c);
    }

    /**
     * sets the color to a RGB component array.
     * 
     * @param rgb   single rgb components to set the object to
     * 
     * @return the new color. 
     * @see ColorModelInterface#setColor(Color)
     */
    @Override
    public final int[] setColor(final int[] rgb) {
        if (rgb.length != 3) {
            throw new IllegalArgumentException("RGB has always 3 components.");
        }
        return setColor(new Color(rgb[0], rgb[1], rgb[2]));
    }

    /**
     * returns the currently representated color
     * 
     * @return a {@link Color} object set to the current color
     */
    @Override
    public final Color getColor() {
        return color;
    }

    /**
     * get the single color components as integer array.
     * 
     * values are stored in the array in order as the name says.
     * 
     * example: RGB -> int[ R, G, B]
     * 
     * @return single color components.
     */
    @Override
    public final int[] getModelColor() {
        return modelColor;
    }

    /**
     * ensure that a given value is between 0 and 255.
     * 
     * This method is usefull for RGB conversation.
     * 
     * @param val   value to check
     * 
     * @return value between 0 and 255
     */
    protected int clip(final int val) {
        if (val < 0) {
            return 0;
        }
        if (val > 255) {
            return 255;
        }
        return val;
    }

    /**
     * dose the same like {@link AbstractColorModel#clip(int)} just with a float value.
     * 
     * @param val   value to check
     * @return integer value between 0 and 255
     */
    protected int clip(final float val) {
        return clip((int) val);
    }

    /**
     * showes the colorspace name and the value.
     * 
     * @return representated color in the colorspace. 
     */
    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer();
        sb.append(getName()).append(" (");
        for (int i = 0; i < getComponentCount(); i++) {
            sb.append(modelColor[i]);
            if (i != getComponentCount() - 1) {
                sb.append(";");
            }
        }
        sb.append(")");
        return sb.toString();
    }

    /**
     * splits the name to the single labels.
     * 
     * @return label names for each slider.
     */
    @Override
    public char[] getColorLabels() {
        final String name = getName();
        final int length = name.length();
        final char[] labels = new char[length];
        for (int i = 0; i < length; i++) {
            labels[i] = name.charAt(i);
        }
        return labels;
    }

    /*
     * Creates a hashcode to identify the object.
     * 
     * @return hashcode from a Color Model
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((color == null) ? 0 : color.hashCode());
        result = prime * result + Arrays.hashCode(modelColor);
        return result;
    }

    /*
     * Compares a ColorModel with another Object
     * 
     * @param obj Object to compare
     * @return evaluates to true if the obj is equal
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof AbstractColorModel)) {
            return false;
        }
        AbstractColorModel other = (AbstractColorModel) obj;
        if (color == null) {
            if (other.color != null) {
                return false;
            }
        } else if (!color.equals(other.color)) {
            return false;
        }
        if (!Arrays.equals(modelColor, other.modelColor)) {
            return false;
        }
        return true;
    }
    
    
}
